// 初始化根元素
let root;

// 扫雷游戏的初始数组
const arr = [
  // 游戏板的初始布局，'X' 表示地雷，空字符串表示没有地雷
  ["", "", "", "", "", "X", "X", "", ""],
  ["", "", "", "X", "", "X", "", "", "X"],
  ["", "X", "X", "", "", "", "", "", "X"],
  ["", "", "", "", "", "", "", "", ""],
  ["", "", "", "", "", "", "", "X", ""],
  ["", "", "X", "", "", "", "", "", ""],
  ["", "", "", "", "", "", "", "", ""],
  ["", "", "", "", "", "", "", "", ""],
  ["", "", "", "", "", "", "", "", ""],
];

// 将数字或 'X' 转换为对应 CSS 类名
function numberToString(num) {
  const classNameMapping = {
    0: "zero",
    1: "one",
    2: "two",
    3: "three",
    4: "four",
    5: "five",
    6: "six",
    7: "seven",
    8: "eight",
    X: "mine", // 'X' 对应的类名为 'mine'，表示地雷
  };
  return classNameMapping[num];
}

// 渲染游戏板
function render(mineArr) {
  // 生成包含HTML表格的字符串
  const table = `<table>
        ${mineArr
          .map(
            (mineItemArr, row) => `
            <tr>
                ${mineItemArr
                  .map(
                    (item, col) => `
                    <td class="${numberToString(item)}" id="${
                      row === 8 && col === 8 ? "sel" : ""
                    }" data-row="${row}" data-col="${col}" data-raw="${item}">
                        ${
                          item == "X"
                            ? ""
                            : item == 0 && item != "X"
                            ? ""
                            : item
                        }
                    </td>
                `
                  )
                  .join("")}
            </tr>
        `
          )
          .join("")}
    </table>`;
  // 将表格字符串设置为根元素的内容，用于在页面上显示游戏板
  root.innerHTML = table;
}

// 游戏结束时的渲染
function endRender() {
  // 创建一个新的<div>元素，用于显示游戏结束的覆盖层
  const div = document.createElement("div");

  // 在新<div>元素内部插入HTML内容，显示游戏结束的信息
  div.innerHTML = `<div class="cover">
        <div class="content">游戏结束</div>
    </div>`;

  // 将新<div>元素添加到根元素的父级，以在页面上显示游戏结束的覆盖层
  root.parentNode.appendChild(div.children[0]);

  // 重新渲染游戏板，显示地雷分布
  render(arr);
}

// 获取周围地雷的数量及无地雷位置
function getAroundAndCount(arr, { row, col }) {
  let count = 0;
  const positionWithoutMineArr = [];

  // 循环遍历当前格子周围的 8 个格子
  for (let i = row - 1; i <= row + 1; i++) {
    for (let j = col - 1; j <= col + 1; j++) {
      // 检查是否为无效位置（越界或当前格子本身）
      const isInvalidPosition =
        i < 0 || j < 0 || i > 8 || j > 8 || (i === row && j === col);
      if (isInvalidPosition) {
        continue; // 跳过无效位置
      }
      if (arr[i][j] === "X") {
        count++; // 如果周围格子是地雷，增加地雷计数
      } else {
        positionWithoutMineArr.push({ row: i, col: j }); // 如果周围格子没有地雷，记录其位置
      }
    }
  }
  arr[row][col] = count; // 更新当前格子的数字，表示周围地雷数量
  return { positionWithoutMineArr, count };
}

// 标记格子是否已经被点击
const flagData = new Array(9).fill("").map(() => new Array(9).fill(false));

// 扫雷算法
function mineSweeperAlgorithms(arr, { row, col }) {
  // TODO：待补充代码
  // 1.
  if(flagData[row][col]) return;
  flagData[row][col] = true;
  // 2.
  const { positionWithoutMineArr, count } = getAroundAndCount(arr, { row, col });
  if (count == 0) {
    positionWithoutMineArr.forEach((item) => {
      mineSweeperAlgorithms(arr, item);
    });
  }
}

// 用于隐藏地雷的数组
let hideMineArr = arr;

// 初始化事件监听器
function initEvent() {
  // 监听游戏板上的点击事件
  document.querySelector("table").addEventListener("click", (e) => {
    if (e.target.nodeName !== "TD") return;
    const row = Number(e.target.dataset.row);
    const col = Number(e.target.dataset.col);
    if (arr[row][col] === "X") {
      // 如果点击的格子是地雷，游戏结束
      endRender();
      return;
    }
    // 执行扫雷算法
    mineSweeperAlgorithms(arr, { row, col });
    // 更新隐藏的游戏板，去除地雷信息，只显示数字
    hideMineArr = arr.map((arrs) =>
      arrs.map((item) => (item === "X" ? "" : item))
    );
    // 重新渲染游戏板
    render(hideMineArr);
    // 重新初始化事件监听器，以便继续游戏
    initEvent();
  });
}

// 初始化游戏
function init(app, data) {
  // 将根元素设置为传入的容器元素
  root = app;
  // 渲染初始游戏板
  render(data);
  // 初始化事件监听器，使游戏可以开始
  initEvent();
}
